package repositories

import (
	"database/sql"
	"errors"
	"gameTest/common"
	"gameTest/datamodels"
)

type IUserRepository interface {
	Conn() error
	Select(userName string) (user *datamodels.User, err error)
	Insert(user *datamodels.User) (userId int64, err error)
	UpdateToken(user *datamodels.User) error
}

func NewUserRepository(table string, db *sql.DB) IUserRepository {
	return &UserManagerRepository{table, db}
}

type UserManagerRepository struct {
	table string
	mysqlConn *sql.DB
}

func (u *UserManagerRepository) Conn() (err error) {
	if u.mysqlConn == nil {
		mysql, errMysql := common.NewMysqlConn()
		if errMysql != nil {
			return  errMysql
		}
		u.mysqlConn = mysql
	}
	if u.table == "" {
		u.table = "user"
	}
	return
}

func (u *UserManagerRepository) Select(userName string) (user *datamodels.User, err error) {
	if userName == "" {
		return  &datamodels.User{}, errors.New("用户账号不能为空")
	}
	if err = u.Conn(); err != nil {
		return  &datamodels.User{}, err
	}
	sql := "SELECT * FROM " + u.table + " WHERE username = ? LIMIT 1"
	rows, errRows := u.mysqlConn.Query(sql, userName)
	defer  rows.Close()
	if errRows != nil {
		return &datamodels.User{}, errRows
	}
	result := common.GetResultRow(rows)
	if len(result) == 0 {
		return &datamodels.User{}, errors.New("用户不存在")
	}
	user = &datamodels.User{}
	common.DataToStructByTagSql(result, user)
	return
}

func (u *UserManagerRepository) Insert(user *datamodels.User) (userId int64, err error) {
	if err = u.Conn(); err != nil {
		return
	}
	sql := "INSERT INTO " + u.table + " SET nickname = ?, username = ?, password = ?, create_at = ?, update_at = ?"
	stmt, errStmt := u.mysqlConn.Prepare(sql)
	if errStmt != nil {
		return userId, errStmt
	}
	result, errResult := stmt.Exec(user.NickName, user.UserName, user.HashPassword, user.CreateAt, user.UpdateAt)
	if errResult != nil {
		return userId, errResult
	}
	return  result.LastInsertId()
}

func (u *UserManagerRepository) UpdateToken(user *datamodels.User) (err error){
	if err := u.Conn(); err != nil {
		return  err
	}
	sql := "UPDATE user SET auth_token = ?, expire_at = ? WHERE id = ?"
	stmt, err := u.mysqlConn.Prepare(sql)
	if err != nil {
		return err
	}
	_, err = stmt.Exec(user.AuthToken, user.ExpireAt, user.ID)
	if err != nil {
		return  err
	}
	return nil
}
